HOST=$(/bin/hostname)
将（）里的命令执行后的结果赋值给HOST变量
#------------------------------------------------^M
/etc/rc.d/

level3的用户login后, 将自动启动一个指定的shell

# ---------------------------------------------
$?  对上一次命令执行成功与否成功$？为0

判断文件是否存在且是否为文件
[ -f file ]
判断文件是否存在且是否为可写文件
[ -w file ]
判断文件是否存在且是否为可执行文件
[ -x file ]
判断文件是否存在且是否为可读文件
[ -r file ]
判断文件是否存在且是否为目录文件
[ -d file ]
判断文件是否存在且是否为空文件
[ -s file ]
判断文件是否存在
[ -e file ]
[]和 test功能一样  -a和-o（和，或）

# ---------------------------------------------
整数值比较判断
[ -eq ]
[ "$a" = "0" ]
(( a % 2 == 0 ))

[ -n string ] string 的长度大于0
[ -z string ] string 的长度为0
 string1=string2  字符串相等
 string1!=string2  字符串不相等
[ int1 -gt int2 ] int1>int2      greater than
[ int1 -ge int2 ] int1>=int2     greater equal
[ int1 -eq int2 ] int1=int2        equal 
[ int1 -ne int2 ] int1!=int2      not equal 
[ int1 -le int2 ] int1<=int2         less equal
[ int1 -lt int2 ] int1<int2       less than
# ---------------------------------------------
符串比较
[ "$a" = "$b" ]
[ -n "$a" ]和 [ "$a" ]一样 判断字符串$a是否为空
[[ "$a" == *"redhat"* ]]和[[ "$a" = *"redhat"* ]]判断-在$a中是否含有redhat字符串
====
数值比较
	1.(())   使用> < == >= <= !=
	2.[]      使用-eq -gt -lt -ne -ge  -le
字符串的比较
	1.[]   = !=
	2.[[]]   ==  --->变量不需要，使用双引号引起来。可以使用通配符号* ?  
	使用> < == >= <= != 不能省略$符号  ,可以进行小数的比较
[root@localhost lianxi]# [[ 4.99 > 3.99 ]]&&echo yes||echo no
yes
[root@localhost lianxi]#
# ---------------------------------------------
if后接的是命令
if rpm -q gcc && id tom||echo "sss"; &&如果前面的命令执行成功则执行&&后的命令否则执行||后面的命令

#---------------------------------------------^M
sed -ri /^#ServerName.*:80$/s/^#// /etc/selinux/config
找出/etc/seliunx/config文件中以#ServerName开头以：80结尾的行
并将#替换成空白
df -Th|grep "/$"|awk '{print $6}'|sed 's/%//'
df后截取某个字段并替换
# ---------------------------------------------
(( a == 50 )) 数值的比较，在(())里用不用$都一样
#-----------------------------------------------^M
$$当前的进程号
数据类型: 仅一种, 即字符串
本地变量, set, 查看当前shell下的所有变量， unset清除一个变量
a=10+20; A="abc def"; $a

间接引用
a=b; b=sxjy; echo ${!a}  显示sxkj    加上{}使变量更加清晰 ！a是取a的值  和{}一起用
----------------------------------------------^M
数学运算：
将运算的结果赋值给一个变量
declare -i c=10+20
c=$[ a+b ]
c=$(( a+b ))
(( c=a+b ))
let c=a+b
能输出结果
 expr 1 + 1
交互模式可以用管道或重定向传值
echo "scale=2;10/3"|bc   计算10/3的值
echo "3.14 > 3.15" | bc  正确输出1
echo "123"|read a
echo -e  后面的字符启用转义
echo -n  输出不换行
read a b c  读入几个变量
---------------------------------------------
以空格结尾
read -s a  读入时不显示输入
read -p " 提示语言" a  设置有提示语言
read -t 3 a 设置3秒不给a赋值脚本继续执行
read   a b <file1 没有循环 将第一个字段赋值给a，第二个字段赋值给b
cat file1
a1 tom a1
a2 jerry aa
a3 mike a34
read a b c <file1
此时 a=a1 b=tom c=a1
# ---------------------------------------------
\s 任意的空白符, 包括空格、制表符(tab)、换行符、中文全角空格
\t 制表符(tab)
\n 换行符
\r 回车符
\w word串, 由字母数字下划线组成的字符串

# ---------------------------------------------
grep awk sed 是基于正则表达式设计的
用双引号将正则表达式引起来 
^行首定位符 ^love 匹配所有以love开头的行
$ \行尾定位符love$匹配所有以love结尾的行
.单个任意字符l..e匹配以l开始后跟两个字符再跟一个e的字符串
*重复0到多个星号前面的字符a* 匹配0个或多个a的字符串
[]匹配一组字符的任意一个[Ll]ove 匹配Love或love的字符串
[x-y]匹配制定范围的一个字符[A-Z]ove匹配大写字符开头后跟ove的字符串
[^]匹配不在指定组内的字符；[^A-Z]配不是大写字母的任意字符
\转义字符用来转义元字符love\.匹配love后跟一个.的字符
!取反
+ 表示一个或多个 xyz+ 一个或多个z
? 表式0个或一个xyz？ 0个或一个z
RE元字符
\< 词首定位符\<love 匹配love开头的词
|> 词尾定位符love\> 匹配love结尾的词
\<bin\> 匹配一个单词
\(..\) 给匹配的字符打上标签(lov)able\1er/ 模式lov被保存为标签1用\1表示
查找一个字符串lov后跟上able，再跟上lov再接上er即：lovablelover
x{m}和x{m,}和x{m,n}字符x重复出现：m次，至少m次，至少m次，并不超过n次
o{5,10} 匹配包含5～10个o的字符串
| 或者
#-----------------------------------^M
echo "tom and jerry"|sed -r 's/(tom) and (jerry)/\2 and \1/'
echo "tom g1,g2,g3 jerry"|cut -d" " -f2
echo "abc def"| sed -r 's/([a-z]+) ([a-z]+)/\2 \1/'
echo "abc def"| sed -r 's/([a-Z0-9]+) ([a-Z0-9]+)/\2 \1/'
echo "abcgood"|grep -E "abc(good)*" --color 匹配abc后有一个或多个good的行
echo "abchidhn"|sed -r 's/(.)(.*)/\1/' 用（）切割字符
echo "abc" |grep -E "abc{3}" {}之前字符c出现的次数为3次
echo "abc defd xyz"|grep -E "\<[a-Z]{3}\>"匹配有三个字母的
echo "abc"| grep -E "abc+" --color
grep -E "^root|^tom" /etc/passwd
echo "abc user@sina.com.cn def"|grep -E "[a-Z0-9._]+@[a-Z0-9.]+\.[a-Z]{2,3}" --color  
#----------------：------------------------------------------------
sed  循环 一行一行的处理文件     行处理
sed -n '/abc/p' file 默认会打印模式空间的内容
行中匹配abc的打印出来  -r  支持扩展分割符
-n不让他默认打印模式空间 
 sed root@10.0.2.253 sed 's/abc/def' file  远程登录后修改file里的内容
sed -n '5p' file 把第五行打印出来
sed -n '$p' file  把最后一行打印出来
sed -n '1，3p' file  把一到三行打印出来
sed -n '1，~3p' file  从第一行开始打印三行
sed  -i '3i aaaaaaa' file  在第三行的前面加上aaaaaaa
sed -i '$a  aaaaa' file  在最后行加入aaaaa
sed  -i '/^tom/i  aaaaaa' file  在以tom开头的行前一行加上aaaaaa
sed  -i  's/abc/def/' file 改每一行的第一个abc成def
sed  -i  's/abc/def/g' file 改每一行的所有abc成def
sed  -i  's/abc/def/3' file 改每一行的第三个abc成def
sed  -i  '1,2s/abc/def/' file 改一到两行abc成def
s 换匹配的字段 c换匹配的行
sed  -i  '1,2s/^.*$/def/' file 改一到两行成def
sed  -i   '4c aaaaaaaaa' file  把第四行改为aaaaaaaa
sed -i  '/^SELINUX/c  selinux ' 把所有以SELINUX开头的行改为selinux
sed -i  '4d' 把第四行删除
sed -i  '/^tom/d' file 删除以tom开头的所有行
sed -i  '/^$/d' file  删除空行
sed -i  '/^\s$/d' file  删除开头为空行\s表示空格或tab
sed  -i '/^abc/s/tom/jerry/'  file  先找到以abc开头的行将这一行的tom改为jerry
sed -i '/^mike/s/^/#' file 将mike行注释
sed  -n  '1p; 3p'  file  打印第一行和第三行
sed -i -e '1s/jerry/tom/;   -e 3s/mike/xyz/'  file  多条一起执行用-e
sed -i '/abc/,/^def/s/123/456/' file  将abc开头的行和def开头的行之间的行的123改为456
sed  -n '1,/def/p' file 从第一行开始直到碰到def的行全部打印出来
#------------------------------------------------------------------------
awk 按行处理行里字段  循环命令
默认以空格作为分割符 默认打印整行$0 -F分割符   制定分割符
awk  'BEGIN{print  "aaaa"}/tom/{print $2}END{print "bbbbbbb"}'  file1
先执行BEGIN里的语句 从文件中读取第一行是否匹配/tom如果有则执行没有就不执行直到读完后，再运行END的语句  可以选用BEGIN  匹配项 ENG。
awk '/^mike/{print $2}' file
awk 'NR==2{print $2}'  file    NR是行号 NF字段数
awk 'NR==2||NR==4{print $2}' file   只读两个固定的行号
awk  '{print $0}' file  $0 整个行
awk 'BENGIN{FS=":" OFS="  "}/bash$/{print $0}' file  FS 指定了分割符：OFS 指定了输出的字段分割符
tr ":" "" 将冒号改为空格
awk 'BEGIN{i=10;echo$i}'
awk -v v1=$a -v v2=$b  'BEGIN{print v1+v2}'  将bash的值传给awk
awk -F： -v v1=$a '$0~v1'{print $0} ~ 匹配条件
awk  'BEGIN{i=0;}{i++}END{print i}' file
awk '/^root/{$3+=10;print $3}' file
awk '$1~"root"{print $1}' file
awk '$1==500{print $1}' file  第一个字段为500
awk '$NF~"bash"{print $1}' file  最后一个字段是否有bash
awk  '$3>=500&&$3<=503{print $2}' file
awk  -F: -v v1=$a '$1~^v1'  file 打印出以变量a开头的行
awk  -F: '{if($1~/^root/)print $1}' file   打印出第一个字段以root开头的行的第一个字段

next  直接读下一行continue
exit 结束不读了break
int（）整数化
awk  'system("useradd" $2)' file   system()调用系统的命令
#---------------------------------------^M
变量
${a}aaa变量a
export a  将本地变量a变成环境变量在子bash也可用
$PATH  路径变量 PATH=$PATH:/$HOME/bin 增加路径
$$  显示当前的进程号
$PPID 父进程号
$USER 当前用户
$UID  当前用户的UID
$HOSTNAME 当前的主机名
$1 $2 $3  $4.... 要传递的参数
shift 将参数向前移动一位
$0 当前的脚本的名称
$# 要传递参数的个数
${!a} 间接取变量a值
$@和$*  所有的位置参数 区别$@最好用双引号$*最好不要用双引号
“$@” 能包括空行 “$*” 所有的参数当成一个看待
for i 相当于for i in “$@”
$RANDOM  随机数
$? 返回值
#----------------------------------------------------……M
for 遇空格或回车算一次
for i in tom jerry do
for i in *.sh
{1..10}相当于1 2 3 4 5 6 7 8 9 10
for i in {1..10}
seq -w 10 等宽09 10
seq 2 2 10 从2到10 每隔一个取一个数
for i in '<file'do
for ((i=0; i<10;i++))
#--------------------------------------------------------
while ((i<=10));do
while true do   a=" " while [$a ];do 相当于while [ -n $a ] do while [ 1 ] do 死循环
cat file|while read a b c；do   每次读一行文件将参数（以空格分割）分别赋值
#--------------------------------------------------------------
case "$c" in
10|20|30)

;;


用.执行脚本在当前下执行
定义函数 function name{}    name()
调用函数  name
函数的返回值默认成功为0 不成功时为别的 可以自己设置 return是返回到$?的值
echo ${a: -1}  得$a的最后一个字
函数中声明局部变量用local声明 否则在shell中变量都可以在脚本中任何一处使用
如果一个脚本要用到另一个脚本里的函数则在脚本里用.执行一下要调用的脚本
#------------------------------------------------------------------------
bash自带的处理字符串
echo ${#a} $a中字符串的个数
echo ${a:3} $a中从第三个开始取直到结束
echo ${a:3:2}$a中从第三个开始去两个字符
echo ${a: -1}取最后一个字符
echo ${a#*.} 从左边开始删除直到遇到.为止
echo ${a##*.} 从左边开始删除直到遇到最后一个.为止
echo ${a%.*}从右面开始删除直到遇到.为止
echo ${a%%.*}从右面开始删除直到遇到最后一个.为止
echo ${a/abc/111} 将变量a中的第一个abc替换成111
echo ${a//abc/xyz}将变量a中的所有的abc替换成xyz
#------------------------------------------------------------------------
shell中常见的工具
seq 
seq 10  1～10
seq  3 10  3～10
seq  3 2 10  3 5 7 9
seq -w 10  同宽输入
seq -s 设置分割符默认为换行
#---------------------------------------------------------------------------
tr 针对字符进行操作
echo "abc 11a22bc" |tr “abc” “xyz” 结果：xyz 11x22yz
tr "abc" "xyz"  <file  处理文件
tr "a-z" "A-Z" <file  将小写字母转成大写字母
tr ":" "\m"
echo "abdcdd"| tr -d "abc"将abc三个字符删除
cat file |tr -d “a-z”
echo “aaaaaaaaxcxxx cccccccc”|tr -s"abc" 将重复的abc字符压缩成一个字符
#----------------------------------------------------------------
sort 排序  文件没改变
默认以空白作为分割符以第一个字段进行排序 （按字符串排asic）
sort -n file  以第一个字段的数值排序
sort -r 倒序
sort -k2  以第二个字段排
sort -t：以：分割字段
#-------------------------------------------------------------------
uniq 去重复行 不改变文件
uniq file  只改变相邻的重复行
uniq -c  显示相邻的重复多少行
uniq -u 只显示没有相邻重复的行
#--------------------------------------------------------------------
cut  分割字符  默认分割符为tab键
cut -d： -f1-f3  file  指定分割符为：只要1  3字段
echo  “addfgg” |cut -c3  取第三个字符
#---------------------------------------------------------------------
grep -n ”root“ /etc/passwd  过滤出来加行数
grep -c ”root“ /etc/passwd  过滤出来的行号
grep -v ”root“ /etc/passwd  取反
grep -q ”root“ /etc/passwd  过滤出来的不显示
grep -w ”root“ /etc/passwd  过滤出来有单词root的行
grep -o ”root“ /etc/passwd  过滤出来root单词
grep -ro ”root“ 目录     过滤出来目录中文件里的有root的行
grep -i ”root“ /etc/passwd  忽略大小写
grep -E ”root“ /etc/passwd  启用扩展正则
grep -f file file1   过滤出file和file1中共同拥有的行
grep -f file file1 -v  过滤出file有file1没有的行
grep -x ”root“ file  过滤file中只含有root的的行
#------------------------------------------------------------------------
find . -nouser  把没有主人的文件找出来
find  .  +size +10000c  找出文件大于10000个字节的文件
find / -maxdepth 1  -name  “*.conf”  -maxdepth  不会找子文件 
find . -perm  600  把权限为600的找出来
find . -name “*.sh”  |xargs  rm -rf {} 把文件找出后交给rm处理
find . -name “*.sh”  |xargs -I{} rm -rf {}  用-I 指定用什么表示查出的内容4

find . -nouser  把没有主人的文件找出来
find . -nouser  把没有主人的文件找出来
find . -nouser  把没有主人的文件找出来
 #----------------------------------------------------
trap 屏蔽信号 
trap '' 2  屏蔽中断信号
trap 'ls;pwd;date' 2 当出发中断信号（ctrl+c） 执行ls；pwd；date；
trap 2 还原

trap 'bash hello.sh' 2 15
收到2和15信号的时候，执行bash hello.sh脚本
#---------------------------------------------
curl -o a.html http://www.sohu.com/index.html 将搜狐的首页下载下载到a.html中
curl -O  http://www.sohu.com/index.html 将搜狐的首页下载下来
curl -T file   ftp://10.0.2.253/ 将file文件上传到10.0.2.253中  用ftp协议
 #------------------------------------------------------------------------
数组名=（值  值）定义数组
echo ${数组名[下标]}
arr=([0]=tom [1]=jerry [2]=mike [4]=lee)
arr=(tom jerry make)
echo ${arr[0]}
arr[x++]=tom
arr[x++]=jerry  arr[0]=tom  arr[1]=jerry
echo ${arr[@]} 数组的所有值
echo ${#arr[@]} 数组的个数
echo ${!arr[@]} 数组的下标
while read a b c; do
arr[x++]=$b  下标从0开始自动加1
done <file2 
#------------------------------------------------------
bash下的特殊符号
* 多个字符 "*" 不在具有通配符的作用
？一个字符
“” 将字符引起来将空白符也包含 所有的符号（如$）依旧有意义
` ` 里的符号就是符号没意义
a=$(rpm -qf $(which ifconfig))
& 放在后台执行 在子shell中执长度行
；命令结束符
将命令放在（）是在子shell中执行的命令（cd /tmp；ls）
{0..9..2}  0~9 增量是2
{1,3,5} 1  3 5
将命令放在{}是在当前shell中执行的命令（以；隔开）
a=5   eval  echo {0..$a}
((a=10+2))  赋值
((a==10 % 3)) 比较
| 两边的命令都是在不同的子shell中执行的
gunzip <aa.gz >a2

cat >file<<EOF   产生一个文件
>ABC
>EOF 

cat <file
#---------------------------------------------------
shell的执行
bash  shell.sh  在子shell中执行 不要x权限
. shell.sh 在当前的shell中执行 不要x权限  和source命令执行一样
用路径执行 要x权限才能执行 在子shell中执行

一般用第三种执行  用bash -x  调试  在调用其它的shell是一定要用第二种
#-----------------------------------------------------
用输入用户名和密码的叫登录shell不用输入的叫非登录shell

登录的shell
登录shell时调用一下环境变量配置文件
全局的变量配置文件 /etc/profile 
第二个文件/etc/profile.d/*.sh
用户的环境配置文件
第三个文件～/.bash_profile
第四个文件~/.bashrc
第五个文件/etc/bashrc
退出时
文件.bash_logout
#----------------------------------------------------------
非登录shell（）
第一个文件 ～/.bashrc
第二个文件/etc/bashrc
第三个文件 /etc/profile.d/*sh














 

R中的metacharacter
^
$
[a-zA-Z0-9]有且仅有1个字符
[^a-z]
. 有且仅有一个字符, 一个空格也是一个字符(换行符\n除外)
abc* 0个或多个c, 将*前面的那一个字符c重复0次或多次
.*
\<bin\> 单词
\b<bin\b 一个单词是bin的

echo "tom and jerry" | sed -r 's/(tom) and (jerry)/\2 and \1/'
从左至右\1 \2 \3 ... \9

echo "tom g1,g2,g3 /home/tom" | sed -r 's/(.*) (.*) (.*)/\2/'
echo "abc def" | sed -r 's/([a-Z]+) ([a-Z]+)/\2 \1/'
echo "abcgood" | grep -E "abc(good)*" --color

echo "abcdef" | sed -r 's/(.)(.*)/\1/'
echo "abcdef" | sed -r 's/(.*)(.)/\2/'

grep -E abc{3} file1 {}前面的那个字符c连续出现3次
{3,}
{3,5}

grep -E "\<[a-Z]{3}\>" file1 --color 3个字符的单词

# ---------------------------------------------
ERE
xyz+	1个或多个z
xyz?	0个或1个z
| 或者
email:	grep -E "[a-Z0-9._]+ @	[a-Z0-9.]+	\.	[a-Z]{2,3}"
url:	grep -E "http://		[a-Z0-9.]+	\.	[a-Z]{2,3}"

# ---------------------------------------------
bash符号与正则元字符的比较
ll *.sh
ll | grep -i ".*\.sh$"

find -iname "*.sh"
find -iregex ".*\.sh$"

# ---------------------------------------------
stream editor, 实现了正则, 主要用来进行文本替换 
一行一行(循环)的读取、处理, 对一整行的处理
先使用行号或正则进行定位, 然后进行p s d c a i
/定界符, 可使用任意的字符如?

sed '/abc/p' file1
读取file1的第一行到pattern space(临时缓冲区, 内存)
对pattern space中的这一行进行/abc/p操作
将pattern space中的这一行打印出来
清空pattern space
读取file1的下一行到pattern space
......

ssh root@10.0.5.6 sed -i 's/abc/def/' file1

sed -n '5p' file1
sed -n '1,5p' file1
sed -n '$p' file1
sed -n '/^root/p' file1

sed '3i abc' file1
sed '$a abc' file1
	
sed -i '2,4s/.*/abc/' file1
echo "30%" | sed 's/%//'
	
sed '/localhost/a ds.com' file1
sed '/root/c aixocm' file1

sed '/abc/d' file1
sed '/abc/!d' file1
sed '3d' file1
sed '1,3d' file1
sed '3,$d' file1
sed '/^$/d' file1
sed '/^\s*$/d' file1

sed 's/root/ROOT/' file1
sed 's/root/ROOT/g' file1
sed 's/root/ROOT/2' file1
sed '/tom/s/jerry/mike/g' file1

echo "ab/c def" | sed 's/ab\/c/xyz/'
echo "a b c" | sed 's/ //g'

引用变量
var1="root"
sed "/$var1/c aixocm" file1
    
行首加#
sed '/ADDR/s/^/#/' file1
	
去行首#
sed '/ADDR/s/^#//' file1
	
多次操作
sed '3s/abc/def/; 5s/abc/yyy/g' file1
sed 's/abc/def/; s/hij/xyz/' file1
sed -e '1,3d' -e 's/tom/jerry/' file1

& 保存查找串以便在替换串中引用
sed 's/tom/&jerry/' file1
	
范围匹配
sed '/abc/,/xyz/s/tom/jerry/' file1 abc到xyz中的
sed '/tom/,/jerry/d' file1
sed -n '/abc/,/xyz/p' file1
sed '1,/tom/d' file1 第1行到第1个匹配tom的行
	
security = share
hosts allow
/etc/sysconfig/selinux
UseDNS no
sed -ri "/IPADDR/s/[0-9.]+/$ip/" ifcfg-eth0

# ---------------------------------------------
awk 'BEGIN{commands}pattern{commands}END{commands}' file1
均可选
awk -F: 'BEGIN{print "start..."}/root/{print $1}END{print "end."}' /etc/passwd

# ---------------------------------------------
﻿﻿与sed一样, 也是一行一行的读取、处理(循环)
sed对一整行进行处理, awk将一行分成数个字段来处理
默认的字段分隔符为空白, 默认就使用了扩展正则, 所以不要什么－E －r之类选项
	
执行过程:
(有的话)执行BEGIN{commands}语句块
从文件或stdin中读取第1行
有无模式匹配, 无则执行{}中的语句
有则检查该整行与模式是否匹配, 匹配, 则执行{}中的语句, 不匹配则不执行{}中的语句
读取下一行, 重复这个过程, 直到所有行被读取完毕
(有的话)执行END{commands}语句块

# ---------------------------------------------
﻿﻿字段分隔符
-F
BEGIN中FS与OFS
echo "abc   def:hij        123" | awk -F"[ \t:]+" '{print $3}'

# ---------------------------------------------
变量
'{print $0, NR, NF, $NF, $(NF-1)}'
'BEGIN{a=3.14; b=3.14; c=a+b; print c}'
	
bash变量传进来
a=9; b=5
awk -v v1=$a -v v2=$b 'BEGIN{print v1/v2}'

# ---------------------------------------------
总行数
awk 'END{print NR}' file1
'BEGIN{i=0}{i++}END{print i}'

# ---------------------------------------------
﻿﻿模式匹配
'/root/{$3+=20; print $3}'
'/^root/{print $1}'
'!/root/{print $1}'
ifconfig -a | grep "^\w" | awk '!/lo/{print $1}'

'NR==2{print $1}'
'NR>=2&&NR<=5{print $1}'
 
'$1~/root/{print $1}' ~匹配 !~不匹配
'$1=="root"{print $1}'
'$3>=500 && $3<=505{print $1} /etc/passwd
'$3+$4>=100{print $1}'

'$1==v1{print $3}' v1是变量
'$0~v1{print $3}'
'$0~"^"v1{print $3}'

awk '/^root/' /etc/passwd 仅有模式匹配, 默认打印$0

# ---------------------------------------------
﻿﻿'{if($1~/root/)print $0}'
'{if($1~/^root/)print $1; else print $2}'
'{if($1~/root/ && NR==1) print $1}'
'{if($1=="root") print $1; else if($1=="ftp") print $2; else print NR}'

next 读取下一行
exit 不再读取下一行, 跳到end语句块
'{if(NR>3) next; print $1}END{print NR}'
'{if(NR>3) exit; print $1}END{print NR}'

# ---------------------------------------------
for
int()
'{printf "%.2f\n", $2/$3}'

# ---------------------------------------------
执行shell命令
a1 tom b1
a2 jerry b2
a3 lee b3
awk '{system("useradd "$2)}' file1
















# ---------------------------------------------
1. 本地变量

2. 环境变量
v1="ds.com"
export v1
    	
PATH 仅对外部命令
别名, 关键字(if for while), 函数, 内部命令, 外部命令

SHLVL
ps $$
PPID

3. 位置参数变量
$0 $1 ... ${10}
	
4. 预定义变量
$0
$#
$@ $* "$@" "$*"
for i相当于for i in "$@"
$?
$RANDOM

# ---------------------------------------------
tar cjf abc.tar.bz2 "$@"
echo "运行 $0 脚本"
echo "共备份 $# 个文件"
echo "文件包括: $@"

# ---------------------------------------------
for i in tom jerry mike
a="tom jerry mike"; for i in $a
for i in /boot/*
for i in *.mp3
for i in `seq -w 10`
for i in {1..10}
for i in `ls`
for i in `<file1`
for i in `cat file1`
for ((i=1; i<=5; i++))

# ---------------------------------------------
循环中的break与continue		

# ---------------------------------------------
取位置参数
for i in "$@"
for ((i=1; i<=$#; i++)); do
	echo ${!i}
shift;

# ---------------------------------------------
﻿while后接的是一条命令
((i<=5))
取位置参数
while true; do
	read str
	if [ "$str" = "end" ]; then
		break;
	fi
done

# ---------------------------------------------
﻿读文件内容
tom g1,g2,g3 /home/tom
jerry g1,g2 /home/jerry
lee g1 /home/lee
while read u g h; do 
	echo $g | cut -d, -f1
done <file1或cat file1 | while

# ---------------------------------------------
﻿无限循环、读文件内容用while, 其它均用for

# ---------------------------------------------
﻿until
与while逻辑相反

# ---------------------------------------------
﻿case
参考/etc/init.d/vsftpd等

# ---------------------------------------------
PS3="input :"
select i in a b c; do
	if [ "$REPLY" = "tom" ];
		bash bind.sh
	fi
done

# ---------------------------------------------
function
返回值
给函数传参数
local
/etc/init.d/functions

# bash standard lib function

# ---------------------------------------------
# function: 判断偶数
# para: 位置参数
# return: 0 or 1
# usage: even 3
# ---------------------------------------------
even() {
	local i=${1: -1}
	case "$i" in
		[02468])  return 0;;
		*)        return 1;;
	esac
}

# ---------------------------------------------
find . -nouser
find / -size +200M
find . -maxdepth 1 -name "*.conf"
find . -perm 600

# ---------------------------------------------
grep: global search regular expression(RE) and print out the line
grep -n --color
grep -c
grep -v "^\s*$"
grep -wq
grep -ro "root" dir1
grep -Ei
grep -f file1 file2
grep -x "abc" file1

# ---------------------------------------------
seq

# ---------------------------------------------
tr
单字符处理工具, 而不是字符串处理工具
cat file1 | tr "abc" "xyz"
a都替换成x, b都替换成y, c都替换成z
并不是将字符串abc替换成字符串xyz
	
tr "a-z" "A-Z" <file1
echo $PATH | tr ":" "\n"
		
cat file1 | tr -d "abc"
所有的a、b、c字符都会被删除, 并不是删除abc字符串
 
echo "123abcXYZ" | tr -d "a-zA-Z" 
cat file1 | tr -d "\n\t"
echo "a b c" | tr –d " "

echo "aaabbbccc" | tr -s "a-zA-Z"
echo "a b  c   d    e" | tr -s " "

删除windows文件中的^M字符(回车符\r)
cat file1 | tr -d "\r"
man bash  | col -b >file1

# ---------------------------------------------
sort默认字段分隔符为空白(与awk一样)
sort -t: /etc/passwd 默认以第1个字段排序
sort -t: -k3nr /etc/passwd

# ---------------------------------------------
先sort再uniq

# ---------------------------------------------
cut默认字段分隔符为tab
cut -d: -f1,3,5
echo "abcdef" | cut -c2

# ---------------------------------------------
find -name "in*" | xargs rm -f
find -name "in*" | xargs -I{} chown tom:tom {}
find -name "in*" | xargs -I{} cp {} /tmp/{}.bak

# ---------------------------------------------
trap 'ls –l; date; cal; fun1' 2
sleep 60
ctrl + c, 触发2

trap '' 2 不做什么
trap 2 复原

# ---------------------------------------------
curl -o小写 a.html http://www.sohu.com
curl -O大写 http://images.sohu.com/bill/s2013/MKT/shipin/huafeihua/450105-0828.jpg
curl -O ftp://10.0.40.1/pub/fstab
curl -T file1 ftp://tom:aixocm@10.0.1.254:21/dir1/ 注意最后/

# ---------------------------------------------
array
0号元素, 1号元素, 2号元素, 目前只支持一维数组
不要求每个元素的数据类型一致, 实际上均为string
    
names=(tom jerry mike)
names=([0]=tom [1]=jerry [3]=mike [5]=lee john)

names[0]=tom
names[1]=jerry
names[2]=lee

names[x++]=tom
names[x++]=jerry
names[x++]=mike
	
for i in "${names[@]}"
for ((i=0; i<${#names[@]}; i++)); do
	echo ${names[i]}

while read a b c; do
	arr[x++]=$a
done <file1
	
a=(`for i in {0..9}; do echo $RANDOM; done`)
for i in `seq 10`; do
	arr[x++]=$RANDOM
done
arr=(`route -n | grep -i "ug"`)
	
v1="abc def hij"
v2=($v1)
	
echo ${!names[@]}
unset names; unset names[2]

# ---------------------------------------------
字符串长度
a="xyz123"
${#a}     

字符所在位置
expr index $a "z"

截取
${a:4}
${a:4:3}
${a: -1}同${a:(-1)}

a="file1.tar.gz"
${a#*.}; ${a##*.}
%

替换
${a/xyz/def}
${a//xyz/def}

shell不需要启动一个单独的进程来运行内部命令, 性能较高, 由bash自带
shell需要创建(fork)和执行(exec)一个新的子进程来运行外部命令

# ---------------------------------------------
bash中的符号

*
?

""
"*"
"ds's keji"
"abc `date` def"
"abc $PATH def"
"!if"
find -name "*.sh"
		
''
	
\
\*
ds\'s\ keji
			
``与$() 
$()可以嵌套
		
; 命令结束符
	
& 在后台运行, 在子shell中运行

()
一组命令, 在子shell中执行
array元素

{}
一组命令, 在当前shell执行
touch a{1,2,3,4,5}
touch a{1..10..2}
${var1}23

a=5
echo {1..$a}
eval echo {1..$a}

((a=10*2))
((a == 10 / 2))

[]  有且仅有1个
ls test[^0-9].sh, ^取反
数组下标
测试, 同test


[[ "$a" == *“abc”* ]]


| 管道两边的命令均在子shell中执行, 在子shell中定义的变量不能传递出来到父shell
	
>  >>  <  << &> &>>
stdin 文件描述符0, 默认是键盘
stdout 1, 默认是终端显示器
stderr 2, 显示器
	
tr "a-z" "A-Z" <file1
gunzip <a1.gz >a2
mysql ds <a.sql    


$ 取变量的值
# 注释


!
执行历史命令
取反
间接取变量的值

echo ${#a}  得到变量的长度
echo ${#a[@]}
echo ${!a[@]}
	
    
空格、制表符、换行符均当作空白
	
&& 
||
if [ $a -eq 0 ] && [ $b -eq 0 ]

# ---------------------------------------------
执行shell脚本的3种方法
G
chmod +x test.sh
./test.sh 在子shell, 常用
	
bash -xv test.sh 在子shell, 一般用来调试脚本
	
source test.sh或.命令, 在当前shell

# ---------------------------------------------
bash的环境变量配置文件

login shell, 输入用户名与密码
	
执行的脚本文件依次如下:
/etc/profile
/etc/profile.d/*.sh
~/.bash_profile
~/.bashrc
/etc/bashrc 注意看最后那个if
		

non login shell
登录系统之后启动的shell
bash命令、在图形中打开终端(gnome-terminal)、su
    
执行的脚本文件依次如下:
~/.bashrc
/etc/bashrc
/etc/profile.d/*.sh

退出登录shell时, 执行~/.bash_logout

# ---------------------------------------------------------------------------------

# ---------------------------------------------
什么是shell编程
shell的作用: 是一个软件, 一个cli, 一门解释型的面向过程的程序设计语言

shell如何解析一个完整的命令行? 命令行的处理过程如下:
1. 历史命令替换
2. 命令行拆分为token(单词)(以空格或tab隔开, 即以空白隔开)
3. 历史更新
4. 处理引用
5. 定义别名替换和函数
6. 建立重定向、后台、管道
7. 变量替换($USER、$NUM等)
8. 命令替换(echo "abc `date` def")
9. 文件名替换(*.conf -> a.conf b.conf)
10. 程序执行(内部命令、外部命令、shell脚本等)

一个命令行在执行之前, shell先将其参数进行替换(解析、扩展)
如将变量替换、命令替换、文件名替换, 最后才执行命令
对二进制程序它解析不了, 它解析的是程序执行之前命令行中的参数

# ---------------------------------------------
方法1
首选项->远程桌面(vino)

# ---------------------------------------------
方法2
tigervnc-server
vncserver :1
service vncserver status
vncserver -kill :1

tigervnc
vncviewer 192.168.0.253:1 -shared -fullscreen -viewonly

# ---------------------------------------------
shell如何执行命令
内部命令是shell解释程序内建的, 由bash直接执行, 不需要派生新的进程

外部命令(external command or disk command)
二进制可执行文件, 需要由磁盘装入内存执行, 会派生新的进程
bash会fork自身的一个拷贝
然后用exec系列函数来执行外部命令
然后外部命令就取代了先前fork的子shell

shell脚本(script)
shell解释程序会fork+exec执行这个脚本
在exec调用中内核会检查脚本的第一行(如#!/bin/sh)
找到用来执行脚本的解释程序, 然后装入这个解释程序, 由它解释执行脚本程序
# ---------------------------------------------



shell脚本是否作为单独的一个进程执行
不是, shell脚本本身不能作为一个进程
shell脚本由一个shell解释程序来解释运行其中的命令
这个shell解释程序是单独的一个进程, 脚本中的外部命令也都作为独立进程依次被运行
这也就是为什么ps不能找到正在运行的脚本的名字的原因了
# ---------------------------------------------
Korn shell的较新的版本(ksh93以后)比较特殊
管道最后一级的命令是在当前shell执行的
这是一个feature而非bug, 在POSIX标准中也是允许的
这样就使下面的命令结构成为可能
cmd | read var
由于read var在当前shell中执行, 所以当前shell中就有var变量

但不是所有的shell都是这样实现的
如开源的pdksh就是在子shell中执行管道的每一级命令
(bash/pdksh/ash/dash均是在子shell中执行)

Korn shell对管道的处理还有一个特殊的地方
就是管道如果在后台执行的话, 管道前面的命令会由最后一级的命令派生
而不是由当前shell派生出来, 据说Bourne shell也有这个特点
但是他们的开源模仿者pdksh和ash却不是这样处理的

# ---------------------------------------------


rsync /dir1/* /dir2/ 将/dir1下的文件同步到/dir2中
将字体文件.ttf文件copy入/usr/share/fonts/chinese/TrueType/下

当linux的字符编码不是utf-8而是gb2312时，smb挂windows分区中文文件名乱码
mount -t cifs //192.168.8.6/e$ /mnt -o username=administrator%password -o iocharset=gb2312即可

fuser -vm /dir1 谁正在访问/dir1
fuser -km /dir1再umount就没有问题了


# ---------------------------------------------


这个和gettext的字符集转换有关

# ---------------------------------------------
系统状态信息
iostat
uptime
w
vmstat
top
free -m
lsof -i:http
ps aux
dmesg
pgrep -x vsftpd
tty

cat /proc/cpuinfo
free
uptime
netstat -s
装sysstat软件包
iostat

# ---------------------------------------------
Linux中清空本机本地的dns缓存(作用同win下的ipconfig /flushdns)
rpm -q nscd(默认有)
/etc/rc.d/init.d/nscd restart
service nscd restart



gunzip zic.8.gz; man ./zic.8

/etc/sudoers(visudo)
tom	rhel5(root)	 /usr/bin/passwd
普通用户	主机名 身份	 可以执行的命令


hdparm -t /dev/sda
vim /etc/fstab->,noatime 禁用日志写入,mount / -o remount就生效了。


与某功能相关的命令:
man -k nfs
man -k lvm
man -k copy
man -k raid
whatis的作用：这条命令是做什么的，如：whatis mdadm


# ---------------------------------------------


某些发行版会在后台运行一个域名解析缓存服务，
当然，也有发行版没有这个服务。如果您的Ubuntu
后台有这个程序，那么您可以用重新启动 nscd
服务的方式来清空缓存。
为啥要清空缓存？
大多数的 DNS 客户端会把域名解析的结果缓存到本地，
这样可以提升对于同一个地址的访问速度。当您打
开一个单页面的时候，通常会有多次对同一个域名
的访问请求。基本上每个文件、图片、样式表……这
些都是在同一个页面内部的对同一个域名的 DNS 解
析请求。
所以如果您已经在本地缓存了不正确的 DNS 条目，
那么您需要清空您的缓存来使 DNS 客户端提出新的
 DNS 请求并更新解析结果。当然，您也可以等缓存
的 DNS 条目过期以后让系统自动冲掉该条目……这
通常需要24个小时。
在 ubuntu 中冲掉 DNS 缓存的方式是重新启动
nscd 守护程序。
安装 nscd 的方式是在命令行中运行这条命令：
sudo aptitude install nscd
在Ubuntu中清 DNS 缓存的命令是：
sudo /etc/init.d/nscd restart


注释多行:
:.,$s/^/#/
:.,+5s/^#//

ls -l	modify time
ls -lc	ctime, i节点被修改, chmod或chown
ls -lu	access time, cat或more
stat

# ---------------------------------------------
取最后一个字符
echo ${a: -1}
echo $a | rev | cut -c1


看文件的第几行
sed -n '5p' file1

awk 'NR==5' file1

head -5 file1 | tail -1


# ---------------------------------------------

$MAILCHECK

LANG=C C即ascii, 或LANG=也可, 自动使用英文
vim /etc/sysconfig/i18n 
echo $LANG
LANG="en_US.UTF-8"
LANG="zh_CN.UTF-8"

man bash | col -b >file1

mount --bind /mnt /var/ftp/rhel6.4

# ---------------------------------------------

linux下phpWeb页面调用命令行
以什么身份执行的shell命令? apache用户
system("ls /etc"); 单双引号均可
system("mkdir /abc");

system("ls; pwd; date", $re);
echo $re;
返回值[0, 255], 0为命令通过, 非0则是错误号码
	
system("iptables -nL"); 执行不了
system("ls /root"); 执行不了
chmod +s /sbin/iptables /bin/ls

